<template>
  <div>
    <a-table
      bordered
      :columns="columns"
      :data-source="data"
      :customHeaderRow="customHeaderRow"
      :pagination="false"
    >
      <template
        slot="cell"
        slot-scope="text, record, index, column"
      >
        <div
          :class="{ highlighted: false }"
          @click="clickCell(record, index, column)"
        >
          <EditCell
            :text="text"
            :column="column"
            :record="record"
            @change="changeCell($event, record, index, column)"
          ></EditCell>
        </div>
      </template>
      <template slot="footer">
        <div :style="topStyle"></div>
        <div :style="bottomStyle"></div>
        <div :style="leftStyle"></div>
        <div :style="rightStyle"></div>
      </template>
    </a-table>
  </div>
</template>
<script>
import EditCell from './EditCell'
import { RuleTableType } from './FCRuleTableConstant'
export default {
  name: 'FCRuleTable',
  props: {
    //table实例
    table: Object,
    //规则表类型
    type: { type: String, default: 'simple' },
    //规则表方向
    direction: { type: String, default: 'column' },
    //是否⾃动⽣成 table body
    autoBuild: { type: Boolean, default: 'false' },
    //列条件因子
    colConditions: Array,
    //行条件因子
    rowConditions: Array,
    //结果因子
    results: Array,
    //初始规则数组
    initDatas: Array,
  },
  components: {
    EditCell,
  },
  data() {
    return {
      //表结构
      columns: [],
      //表数据
      data: [],
      //已定义的规则集合
      rules: [],
      //列结果
      colResults: [],
      //行结果
      rowResults: [],
      //单元格结果
      cellResults: [],
      //鼠标状态
      mouseStatus: '',
      //选中表格头部的dataIndexs
      selectHeadDataIndexs: [],
      //选中边框
      selectBorder: {
        top: 0,
        left: 0,
        width: 0,
        height: 0,
      },
    }
  },
  computed: {
    topStyle() {
      return {
        position: 'absolute',
        background: '#2c78eb',
        top: this.selectBorder.top - 1 + 'px',
        left: this.selectBorder.left + 'px',
        width: this.selectBorder.width + 'px',
        height: '2px',
      }
    },
    bottomStyle() {
      return {
        position: 'absolute',
        background: '#2c78eb',
        top: this.selectBorder.top + this.selectBorder.height - 1 + 'px',
        left: this.selectBorder.left + 'px',
        width: this.selectBorder.width + 'px',
        height: '2px',
      }
    },
    leftStyle() {
      return {
        position: 'absolute',
        background: '#2c78eb',
        top: this.selectBorder.top + 'px',
        left: this.selectBorder.left - 1 + 'px',
        width: '2px',
        height: this.selectBorder.height + 'px',
      }
    },
    rightStyle() {
      return {
        position: 'absolute',
        background: '#2c78eb',
        top: this.selectBorder.top + 'px',
        left: this.selectBorder.left + this.selectBorder.width - 1 + 'px',
        width: '2px',
        height: this.selectBorder.height + 'px',
      }
    },
  },
  watch: {
    type() {
      this.initResults()
    },
    initDatas() {
      this.initRules()
    },
    colConditions: {
      handler() {
        this.columns = this.buildTableColumns()
        this.data = this.buildTableDataSource()
      },
      deep: true,
    },
    rowConditions: {
      handler() {
        this.columns = this.buildTableColumns()
        this.data = this.buildTableDataSource()
      },
      deep: true,
    },
    rules: {
      handler() {
        this.data = this.buildTableDataSource()
      },
      deep: true,
    },
  },
  created() {
    console.log(RuleTableType, 'RuleTableType')
    this.initRuleTable()
    // this.generateTable()
    this.columns = this.buildTableColumns()
    this.data = this.buildTableDataSource()
    // columns: tableInstance.buildTableColumns(),
    // //表数据
    // dataSource: tableInstance.buildTableDataSource(),
  },
  methods: {
    //初始化RuleTable
    initRuleTable() {
      this.table.init(this)
      this.initRules()
      this.initResults()
    },
    //初始化rules
    initRules() {
      const factorsKeys = this.colConditions.concat(this.rowConditions).map((item) => item.code)
      const resultsKeys = this.results.map((item) => item.code)
      const rules = []
      this.initDatas.forEach((data, index) => {
        const condition = {}
        const result = {}
        Object.keys(data).forEach((key) => {
          if (factorsKeys.includes(key)) {
            condition[key] = data[key]
          }
          if (resultsKeys.includes(key)) {
            result[key] = data[key]
          }
        })
        rules.push({ key: 'key_' + index, condition, result })
      })
      this.rules = rules
      console.log(this.rules, 'this.rules')
    },
    //初始化results
    initResults() {
      const { type, results } = this
      this.colResults = type === RuleTableType.simple ? results : []
      this.rowResults = []
      this.cellResults = type === RuleTableType.complex ? results : []
    },

    //初始化因子属性
    initFactorsAttribute() {
      const { colConditions = [], rowConditions = [], results = [] } = this
      colConditions.concat(rowConditions, results).forEach((item) => {
        item.key = item.code
        if (item.isEnum && item.options) {
          item.options.forEach((item) => {
            item.key = item.value
          })
        }
      })
    },

    //构建表格columns
    buildTableColumns() {
      let columns = []
      const { type, direction, rowConditions, colConditions, results } = this
      //简单决策表
      if (type === 'simple' && direction === 'column') {
        colConditions.concat(results).forEach((item, index) => {
          columns.push({
            title: item.title,
            dataIndex: item.key ?? item.code,
            colIndex: index,
            colTitle: item.title,
            key: item.key ?? item.code,
            headRowIndex: 0,
            isEnum: item.isEnum,
            options: item.options,
            ellipsis: true,
            align: 'center',
            isSimple: true,
            scopedSlots: { customRender: 'cell' },
          })
        })
      }
      //复杂决策表
      if (type === 'complex') {
        let rowCodeArr = rowConditions.map((item) => item.code)
        const colCodeArr = colConditions.map((item) => {
          const key = item.code
          return item.options?.map((item) => ({ [key]: item }))
        })
        if (!rowCodeArr.length && !colCodeArr.length) return

        rowCodeArr = !rowCodeArr.length && colCodeArr.length ? [] : rowCodeArr
        columns = this.generateTableColumns(rowConditions)
        const rowCodeReserve = colConditions.map((item) => ({ [item.code]: item.title })).reverse()
        const rowReserve = [...colConditions].reverse()
        rowCodeReserve.forEach((item, i) => {
          // 在数组第一行添加
          columns?.unshift({
            title: Object.values(item)[0],
            dataIndex: Object.keys(item)[0],
            key: Object.keys(item)[0],
            ellipsis: true,
            width: 120,
            align: 'center',
            isRowHead: true,
            customRender: (value, record, index) => {
              const rowLen = i >= 1 ? (rowReserve[i - 1]?.options.length || 1) * i : 1
              if (index % rowLen === 0) {
                return {
                  children: value,
                  attrs: {
                    rowSpan: rowLen,
                  },
                  style: {
                    color: '#A00',
                  },
                }
              } else {
                return {
                  children: value,
                  attrs: {
                    rowSpan: 0,
                  },
                  style: {
                    color: '#A00',
                  },
                }
              }
            },
          })
        })
      }
      console.log(columns, 'columns')
      return columns
    },
    //构建表格dataSourse
    buildTableDataSource() {
      const { type, autoBuild, colConditions, rules } = this
      let data = []
      if (type === 'simple' && autoBuild) {
        if (rules) {
          rules.forEach((rule, index) => {
            data.push({ key: `key_${index}`, ...rule.condition, ...rule.result })
          })
        } else {
          data.push({ key: 'key_0' })
          columns.forEach((item) => {
            data[0][item.dataIndex] = ''
          })
        }
      }
      if (type === 'complex') {
        const colCodeArr = colConditions.map((item) => {
          const key = item.code
          return item.options?.map((item) => ({ [key]: item }))
        })
        data = this.generateTableCols(colCodeArr)
        let resultCode = ''
        if (this.cellResults.length) {
          resultCode = this.cellResults[0].code
        }
        rules.forEach((rule) => {
          let colKey = ''
          let rowKey = ''
          this.colConditions.forEach((colFactor) => {
            colKey = colKey ? colKey + '_' + rule.condition[colFactor.code] : rule.condition[colFactor.code]
          })
          this.rowConditions.forEach((rowFactor) => {
            rowKey = rowKey ? rowKey + '_' + rule.condition[rowFactor.code] : rule.condition[rowFactor.code]
          })
          data.forEach((item) => {
            if (item.key === colKey) {
              item[rowKey] = rule.result[resultCode]
            }
          })
        })
      }
      console.log(data, 'data')
      return data
    },

    /**
     * 递归生成表格columns
     * @param {Array} rowConditions 行因子
     * @param {Number} depth 层级
     * @param {String} results 前一层级dataIndex
     * @param {Number} datas 前一层级index
     */
    generateTableColumns(rowConditions, depth = 0, preDataIndex, preIndex) {
      if (rowConditions.length === 0) {
        return [
          {
            title: '结果集',
            dataIndex: 'result',
            key: 'result',
            align: 'center',
            scopedSlots: { customRender: 'cell' },
          },
        ]
      }
      if (depth >= rowConditions.length) {
        return []
      }
      return rowConditions[depth].options?.map((item, index) => {
        let title = `${item.label}`
        let dataIndex = preDataIndex ? `${preDataIndex}_${item.key ?? item.value}` : `${item.key ?? item.value}`
        const children = this.generateTableColumns(rowConditions, depth + 1, dataIndex, index)
        if (children.length > 0) {
          return { title, dataIndex, key: dataIndex, headRowIndex: depth, children }
        }
        return {
          title,
          dataIndex,
          colIndex: depth === rowConditions.length - 1 ? preIndex * rowConditions.length + index : null,
          colTitle: dataIndex,
          key: dataIndex,
          headRowIndex: depth,
          ellipsis: true,
          align: 'center',
          scopedSlots: { customRender: 'cell' },
        }
      })
    },
    /**
     * 递归生成列因子表头
     * @param {Array} arr 列因子codeArr
     * @param {Number} index 层级
     * @param {Object} results 前一层级结果和当前的键值对
     */
    generateTableCols(arr, index = 0, current = {}) {
      // 结果数组
      let result = []
      // 如果索引等于数组的长度，意味着已经处理完所有数组
      if (index === arr.length) {
        return [current]
      }
      // 遍历当前层级的数组
      arr[index]?.forEach((obj, i) => {
        // 对于数组中的每个对象，获取键和值
        const key = Object.keys(obj)[0]
        const value = obj[key]
        // 创建一个新的对象，包含之前的结果和当前的键值对
        const newCurrent = {
          ...current,
          [key]: `${value.label}`,
          key: current.key ? current.key + '_' + value.value : value.value,
        }
        // 递归调用，处理下一个数组
        const nextResult = this.generateTableCols(arr, index + 1, newCurrent)
        // 将结果合并到最终结果数组中
        result = result.concat(nextResult)
      })
      return result
    },
    /**
     *合并表头
     * @param {Arary} columns 表头配置项
     * @param {Array} 需要合并表头的项的dataIndex
     */
    mergeHead(columns = [], mergeDataIndexs = []) {
      //应改成合并columns -TODO
      if (mergeDataIndexs.length < 2) {
        return
      }
      const firstCol = mergeDataIndexs[0]
      const otherColList = mergeDataIndexs.slice(1)
      const firstObj = this.findColByDataIndex(columns, firstCol)
      let firstColNum = 0
      if (!firstObj.mergeDataIndexs?.length) {
        otherColList.forEach((item) => {
          const otherObj = this.findColByDataIndex(columns, item)
          this.$set(otherObj, 'colSpan', otherObj.children ? 0 - otherObj.children.length : 0)
          firstColNum += otherObj.children ? otherObj.children.length : 0
        })
        if (firstCol) {
          this.$set(firstObj, 'colSpan', firstObj.children ? firstColNum : mergeDataIndexs.length)
          firstObj.mergeDataIndexs = mergeDataIndexs
        }
      }
    },
    /**
     *拆分表头
     * @param {Arary} columns 表头配置项
     * @param {Array} 需要拆分表头的项的dataIndex
     */
    splitHead(columns = [], splitDataIndexs = []) {
      splitDataIndexs.forEach((item) => {
        const obj = this.findColByDataIndex(columns, item)
        if (obj.mergeDataIndexs) {
          obj.mergeDataIndexs.forEach((mergeItem) => {
            const mergeObj = this.findColByDataIndex(columns, mergeItem)
            if (mergeObj) this.$set(mergeObj, 'colSpan', null)
          })
          obj.mergeDataIndexs = []
        }
      })
    },
    //改变单元格值
    changeCell(newValue, record, rowIndex, column) {
      if (column.mergeDataIndexs) {
        column.mergeDataIndexs.forEach((item) => {
          this.data[rowIndex][item] = newValue
        })
      } else {
        this.data[rowIndex][column.dataIndex] = newValue
      }
      //同步rules或者datas -TODO
    },
    //寻找行的值
    findRow(record, columns) {
      const keysToRemove = columns.filter((condition) => condition.isRowHead).map((condition) => condition.dataIndex)
      const filteredKeys = Object.keys(record).filter((key) => !keysToRemove.includes(key))
      return filteredKeys.reduce((result, key) => {
        result[key] = record[key]
        return result
      }, {})
    },
    //寻找列的值
    findCol(column, data) {
      const col = []
      data.forEach((item) => {
        col.push(item[column.dataIndex])
      })
      return col
    },
    //自定义表头
    customHeaderRow() {
      return {
        class: 'myClass',
        on: {
          mousedown: (e) => {
            this.mouseStatus = 'mousedown'
            this.selectHeadDataIndexs = []
            //表头背景色清空/选中
            if (e.target.tagName === 'TH') {
              e.currentTarget.parentNode.querySelectorAll('th').forEach((item) => {
                // item.style.backgroundColor = '#fafafa'
              })
              const column = this.findColByDataIndex(this.columns, e.target.getAttribute('key'))
              if (!column.isRowHead) {
                // e.target.style.backgroundColor = '#91cbfb'
                this.selectBorder.top = e.target.offsetTop
                this.selectBorder.left = e.target.offsetLeft
                this.selectBorder.width = e.target.offsetWidth
                this.selectBorder.height = e.target.offsetHeight
                e.target.style.cursor = 'crosshair'
                this.selectHeadDataIndexs.push(e.target.getAttribute('key'))
              }
            }
          },
          mousemove: (e) => {
            if (e.target.tagName === 'TH' && this.mouseStatus === 'mousedown') {
              this.selectBorder.width = 0
              //根据mousedown鼠标位置计算选中区域
              const start = this.selectHeadDataIndexs[0]
              const end = e.target.getAttribute('key')
              if (!(start && end)) {
                return
              }
              const selectDataIndex = this.findAllDataIndexs(this.columns, start, end)
              // const selectDataIndex = this.findAllDataIndexs(this.columns, 'name1', 'name1_age1')
              e.currentTarget.parentNode.querySelectorAll('th').forEach((item) => {
                if (selectDataIndex.includes(item.getAttribute('key'))) {
                  // item.style.backgroundColor = '#91cbfb'
                  this.selectBorder.width = this.selectBorder.width += item.offsetWidth
                } else {
                  // item.style.backgroundColor = '#fafafa'
                }
              })
              e.target.style.cursor = 'crosshair'
              this.selectHeadDataIndexs = selectDataIndex
            }
          },
          mouseup: (e) => {
            this.mouseStatus = 'mouseup'
            e.currentTarget.parentNode.querySelectorAll('th').forEach((item) => {
              item.style.cursor = 'default'
            })
            console.log(this.selectHeadDataIndexs, 'selectHeadDataIndexsd')
          },
        },
      }
    },
    //递归遍历寻找columns节点
    findColByDataIndex(columns = [], dataIndex) {
      let obj = null
      columns.forEach((item) => {
        if (item.dataIndex === dataIndex) {
          obj = item
          return
        }
        if (!obj && item.children) {
          obj = this.findColByDataIndex(item.children, dataIndex)
          return
        }
      })
      return obj
    },
    //递归遍历寻找columns的父级columns节点
    findParentColByDataIndex(columns = [], dataIndex, parentCol = null) {
      let obj = parentCol
      columns.forEach((item) => {
        if (!obj && item.children) {
          obj = this.findParentColByDataIndex(item.children, dataIndex, item)
          return
        }
      })
      return obj
    },
    //表头根据鼠标点击和滑动区域，找出所有高亮区域
    findAllDataIndexs(columns, start, end) {
      const isSame = this.isStartEndSame(columns, start, end)
      const isSameParent = this.isStartEndSameParent(columns, start, end)
      return this.findDataIndexsByStartEnd(columns, start, isSame && isSameParent ? end : start)
    },
    //判断表头选中单元格是否在同一行
    isStartEndSame(columns, start, end) {
      const startHeadRowIndex = this.findColByDataIndex(columns, start)?.headRowIndex
      const endHeadRowIndex = this.findColByDataIndex(columns, end)?.headRowIndex
      return startHeadRowIndex === endHeadRowIndex
    },
    //判断表头选中单元格是否在同一个父级下
    isStartEndSameParent(columns, start, end) {
      const startParent = this.findParentColByDataIndex(columns, start)?.dataIndex
      const endParent = this.findParentColByDataIndex(columns, end)?.dataIndex
      return startParent === endParent
    },
    //表头根据鼠标点击和滑动区域，找出选中高亮的dataIndex
    findDataIndexsByStartEnd(columns, start, end) {
      let startIndex = 0
      let endIndex = 0
      let isStart = false
      let isEnd = false
      let selectDataIndex = []
      columns.forEach((item, index) => {
        if (item.children) {
          selectDataIndex = selectDataIndex.concat(this.findAllDataIndexs(item.children, start, end))
        }
        if (item.dataIndex === start) {
          startIndex = index
          isStart = true
          selectDataIndex.push(item.dataIndex)
        }
        if (item.dataIndex === end) {
          endIndex = index
          isEnd = true
          if (!selectDataIndex.includes(item.dataIndex)) {
            selectDataIndex.push(item.dataIndex)
          }
        }
        if (isStart && index > startIndex && !isEnd) {
          if (!selectDataIndex.includes(item.dataIndex)) {
            selectDataIndex.push(item.dataIndex)
          }
        }
      })
      return selectDataIndex
    },
    //点击单元格
    clickCell(record, index, column) {},
    //获取表格columns
    getColumns() {
      return this.columns
    },
    //获取表格data
    getData() {
      return this.data
    },
    //合并表头
    merge() {
      console.log('合并表头')
      this.mergeHead(this.columns, this.selectHeadDataIndexs)
      this.clearSelectTable()
    },
    //拆分表头
    split() {
      console.log('拆分表头')
      this.splitHead(this.columns, this.selectHeadDataIndexs)
      this.clearSelectTable()
    },
    //清除表头选中框及选中数组
    clearSelectTable() {
      this.selectHeadDataIndexs = []
      this.selectBorder = {
        top: 0,
        left: 0,
        width: 0,
        height: 0,
      }
    },
  },
}
</script>
<style scoped>
#table {
  position: relative;
}
::v-deep .ant-table-thead > tr > th {
  padding: 5px 5px;
}
::v-deep .ant-table-tbody > tr > td {
  padding: 0;
}
::v-deep .ant-table-thead {
  user-select: none;
}
/* 实现样式穿透 */
::v-deep .ant-table-tbody > tr.ant-table-row:hover > td {
  background: none !important;
}
::v-deep .ant-table-align-center {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
::v-deep .ant-table-footer {
  padding: 0;
  position: static;
}
.highlighted {
  /* border: 1px solid #2c78eb; */
}
</style>
